package org.softee.numbertext;

import java.math.BigDecimal;
import java.math.BigInteger;

public class NumberTextDa extends NumberText {
    private static final String[] ORDER3 = {"", "tusind", "millioner", "milliarder", "billioner", "billiarder",
        "Trillion", "Trilliard", "Kvadrillion", "Kvadrilliard", "Kvintillion", "Kvintilliard", "Sekstillion", "Sekstilliard",
        "Septillion", "Septiliard", "Oktillion", "Oktilliard", "Nonillion", "Nonilliard", "Decillion"};
    private static final String HUNDRED = "hundrede";
    private static final String[] TEENS = {"(ti)", "elleve", "tolv", "tretten", "fjorten", "femten", "seksten", "sytten", "atten", "nitten"};
    private static final String[] TENS = {"(nul)", "ti", "tyve", "tredive", "fyrre", "halvtres", "tres", "halvfjerds", "firs", "halvfems"};
    private static final String[] ONES = {"(nul)", "en", "to", "tre", "fire", "fem", "seks", "syv", "otte", "ni"};
    private static final String[] ONES_NEUTRAL = {"(nul)", "et", "to", "tre", "fire", "fem", "seks", "syv", "otte", "ni"};
    private static final String ZERO = "nul";
    private static final String AND = "og";
    private static final String MINUS = "minus";
    private static final int RESERVE = 200;


    public NumberTextDa() {
        super(MINUS);
    }

    @Override
    protected String formatPositive(final BigInteger number) {
        if (number.signum() == 0) {
            return ZERO;
        }
        StringBuilder sb = new StringBuilder(RESERVE);
        BigInteger remainder = number;
        int level = 0; // start with ones, then thousands, millions ...
        while (remainder.signum() > 0) {
            if (level == ORDER3.length) {
                throw new IllegalArgumentException("Number too large: " + number);
            }
            // only thousands should be rendered with "et", all others with "en"
            String[] ones = (level == 1) ? ONES_NEUTRAL : ONES;
            String unit = ORDER3[level++];
            BigInteger[] next = remainder.divideAndRemainder(BIG_THOUSAND);
            remainder = next[0];
            int hundreds = next[1].intValue();
            String levelText = hundreds(hundreds, ones, unit);
            if (sb.length() > 0) {
                sb.insert(0, SPACE);
            }
            sb.insert(0, levelText);
        }
        return sb.toString();
    }

    protected String hundreds(long number, String[] onesText, String unit) {
        checkRange(number, 0, 999);
        int hundreds = (int) (number / 100);
        int remainder = (int) (number % 100);
        StringBuilder sb = new StringBuilder(RESERVE);
        if (hundreds != 0) {
            sb.append(ONES_NEUTRAL[hundreds]).append(SPACE).append(HUNDRED);
        }
        if (hundreds != 0 && remainder != 0) {
            sb.append(SPACE);
        }
        if (remainder != 0 || hundreds == 0) {
            sb.append(tens(remainder, onesText));
        }
        if (!unit.isEmpty()) {
            sb.append(SPACE).append(unit);
        }
        return sb.toString();
    }

    protected String tens(long i, String[] onesText) {
        checkRange(i, 0, 99);
        int tens = (int) (i / 10);
        int ones = (int) (i % 10);
        if (i > 10 && i < 20) {
            return TEENS[ones];
        }
        StringBuilder sb = new StringBuilder(RESERVE);
        if (ones != 0) {
            if (tens == 0) {
                sb.append(onesText[ones]);
            } else {
                sb.append(ONES[ones]).append(AND);
            }
        }
        if (tens != 0) {
            sb.append(TENS[tens]);
        }
        return sb.toString();
    }

    @Override
    public BigDecimal parse(String numberText) {
        throw new UnsupportedOperationException("parse");
    }
}
